﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace SharpSoft.WPF.Controls
{
    public class EllipsePanel : Panel
    {

        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement element in base.InternalChildren)
            {
                element.Measure(availableSize);
            }
            return base.MeasureOverride(availableSize);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            var children = base.InternalChildren;

            var center = new Point(finalSize.Width * this.EllipseCenter.X, finalSize.Height * this.EllipseCenter.Y);//转换百分比坐标到实际坐标
            var es = new Size(finalSize.Width * this.EllipseWidth, finalSize.Height * this.EllipseHeight);//转换百分比尺寸到实际尺寸
            var rect = new Rect(center.X - es.Width / 2, center.Y - es.Height / 2, es.Width, es.Height);

            double angle = this.StartAngle;
            double gapA = 0;
            if (this.GapAngle.HasValue)
            {
                gapA = this.GapAngle.Value;
            }
            else
            {
                gapA = 360d / children.Count;
            }
            for (int i = 0; i < children.Count; i++)
            {
                var c = children[i];
                var p = GetArcPoint(rect, angle);
                var s = c.DesiredSize;
                c.Arrange(new Rect(p.X - s.Width / 2, p.Y - s.Height / 2, s.Width, s.Height));
                angle += (this.ClockwiseDirection ? gapA : -gapA);

            }
            return finalSize;
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property==StartAngleProperty
                ||e.Property== GapAngleProperty
                || e.Property == EllipseCenterProperty
                || e.Property == EllipseWidthProperty
                || e.Property == EllipseHeightProperty
                || e.Property == ClockwiseDirectionProperty
                )
            {
                this.InvalidateArrange();

            }
        }
        #region props


        /// <summary>
        /// 起始角度
        /// </summary>
        public double StartAngle
        {
            get { return (double)GetValue(StartAngleProperty); }
            set { SetValue(StartAngleProperty, value); }
        }

        public static readonly DependencyProperty StartAngleProperty =
            DependencyProperty.Register("StartAngle", typeof(double), typeof(EllipsePanel), new PropertyMetadata(0d));


        /// <summary>
        /// 间隔角度,为null表示按元素个数平均分配
        /// </summary>
        public double? GapAngle
        {
            get { return (double?)GetValue(GapAngleProperty); }
            set { SetValue(GapAngleProperty, value); }
        }

        public static readonly DependencyProperty GapAngleProperty =
            DependencyProperty.Register("GapAngle", typeof(double?), typeof(EllipsePanel), new PropertyMetadata(null));



        /// <summary>
        /// 椭圆的中心位置
        /// </summary>
        public Point EllipseCenter
        {
            get { return (Point)GetValue(EllipseCenterProperty); }
            set { SetValue(EllipseCenterProperty, value); }
        }

        public static readonly DependencyProperty EllipseCenterProperty =
            DependencyProperty.Register("EllipseCenter", typeof(Point), typeof(EllipsePanel), new PropertyMetadata(new Point(0.5, 0.5)));



        /// <summary>
        /// 椭圆宽度
        /// </summary>
        public double EllipseWidth
        {
            get { return (double)GetValue(EllipseWidthProperty); }
            set { SetValue(EllipseWidthProperty, value); }
        }

        public static readonly DependencyProperty EllipseWidthProperty =
            DependencyProperty.Register("EllipseWidth", typeof(double), typeof(EllipsePanel), new PropertyMetadata(0.9d));


        /// <summary>
        /// 椭圆高度
        /// </summary>
        public double EllipseHeight
        {
            get { return (double)GetValue(EllipseHeightProperty); }
            set { SetValue(EllipseHeightProperty, value); }
        }

        public static readonly DependencyProperty EllipseHeightProperty =
            DependencyProperty.Register("EllipseHeight", typeof(double), typeof(EllipsePanel), new PropertyMetadata(0.9d));


        /// <summary>
        /// 是否为顺时针方向排列
        /// </summary>
        public bool ClockwiseDirection
        {
            get { return (bool)GetValue(ClockwiseDirectionProperty); }
            set { SetValue(ClockwiseDirectionProperty, value); }
        }

        public static readonly DependencyProperty ClockwiseDirectionProperty =
            DependencyProperty.Register("ClockwiseDirection", typeof(bool), typeof(EllipsePanel), new PropertyMetadata(true));



        #endregion


        #region functions

        /// <summary>
        /// 获取椭圆上的点
        /// </summary>
        /// <param name="lpRect">定义椭圆的矩形框</param>
        /// <param name="angle">角度</param>
        /// <returns></returns>
        public Point GetArcPoint(Rect lpRect, double angle)
        {
            Point pt = new Point();
            double a = lpRect.Width / 2.0f;
            double b = lpRect.Height / 2.0f;
            if (a == 0 || b == 0) return new Point(lpRect.X, lpRect.Y);

            //弧度
            double radian = angle * Math.PI / 180.0f;

            //获取弧度正弦值
            double yc = Math.Sin(radian);
            //获取弧度余弦值
            double xc = Math.Cos(radian);
            //获取曲率  r = ab/\Sqrt((a.Sinθ)^2+(b.Cosθ)^2
            double radio = (a * b) / Math.Sqrt(Math.Pow(yc * a, 2.0) + Math.Pow(xc * b, 2.0));

            //计算坐标
            double ax = radio * xc;
            double ay = radio * yc;
            pt.X = (int)(lpRect.X + a + ax);
            pt.Y = (int)(lpRect.Y + b + ay);
            return pt;
        }


        #endregion
    }
}
